/** 
    Copyright 2010 Henrik Andersson
    
    This file is part of Loopist.

    Loopist is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Loopist is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Loopist.  If not, see <http://www.gnu.org/licenses/>.
*/

package se.dinamic.loopist;

import java.io.InputStream;
import java.nio.ByteBuffer;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.content.Context;
import android.media.SoundPool;
import android.media.AudioManager;

import android.widget.Spinner;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.CheckBox;
import android.widget.Toast;

public class LoopistActivity extends Activity
{
	private LoopistEngine _loopistEngine;
	private LoopistView _loopistView;
	private static Context _context;
	private static Spinner _barsSpinner;
	private static Spinner _beatsPerBarSpinner;
	private static EditText _bpmValue;
	private static ImageView _bpmTapButton;
	private static CheckBox _generateMetronomeTrack;
	
	private static final SoundPool _soundPool=new SoundPool(1,AudioManager.STREAM_MUSIC,0);
	private static int _spClickID=0;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
	getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN ); 	    
	_context=this;
	    
	_spClickID = _soundPool.load(this,R.raw.click,1);
	    
	setContentView(R.layout.new_project);
	
	// Metronome track checkbox
	_generateMetronomeTrack = (CheckBox) findViewById(R.id.generate_metronome_track_cb);
	    
	// Bars spinner
	_barsSpinner = (Spinner) findViewById(R.id.bars_spinner);
	ArrayAdapter adapter = ArrayAdapter.createFromResource( this, R.array.bars, android.R.layout.simple_spinner_item);
	adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	_barsSpinner.setAdapter(adapter);
	_barsSpinner.setSelection(3);
	    
	// Beats per bar spinner
	_beatsPerBarSpinner = (Spinner) findViewById(R.id.beats_per_bar_spinner);
	adapter = ArrayAdapter.createFromResource( this, R.array.bpb, android.R.layout.simple_spinner_item);
	adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	_beatsPerBarSpinner.setAdapter(adapter);
	_beatsPerBarSpinner.setSelection(2);
	    
	// BPM tap button handler
	_bpmValue=(EditText)findViewById(R.id.bpm_value);
	_bpmTapButton = (ImageView) findViewById(R.id.bpm_tap_button);
	_bpmTapButton.setOnTouchListener( 
		new View.OnTouchListener() 
		{ 
			private int _nextTapImage=R.drawable.tap2;
			private long _lastMillis=0;
			private float _averageDelay = 0;
			
			private int _tapCount=0;
			private long [] _delays={0,0};
			
			public boolean onTouch(View v, MotionEvent event)
			{
				
				if( event.getAction() == MotionEvent.ACTION_DOWN ) {
					long current = System.currentTimeMillis();
					_bpmTapButton.setImageResource( _nextTapImage );
					_soundPool.play(_spClickID,0.6f,0.6f,1,0,1.0f);
					if( _nextTapImage == R.drawable.tap1 ) _nextTapImage=R.drawable.tap2;
					else _nextTapImage = R.drawable.tap1;
					
					_delays[_tapCount]=(current - _lastMillis);
					
					if( _delays[_tapCount]  != current  && _delays[_tapCount]  < 2000 ) {
						// Lets scale down precision of delay to 10th ms..
						_delays[_tapCount] = ((long)(_delays[_tapCount] /10))*10;
						Log.v("Loopist",_delays[_tapCount] +"ms since last tap...");
						_tapCount++;
						if( _tapCount == 2 ) {
							
							int avgd = (int) ((_delays[0]+_delays[1] ) / 2.0f);
							
							// Let's also smooth the delay with average value...
							if( _averageDelay > 0)
								_averageDelay = (_averageDelay + ((_averageDelay + avgd )/2.0f)) / 2.0f;
							else 
								_averageDelay = avgd;
							
							_tapCount=0;
						}
						
						// So lets update textview to show BPM
						if( _averageDelay > 0 ) {
							float bpm = (60000.0f/_averageDelay);
							_bpmValue.setText( Integer.toString( (int)bpm) );
						}
						
						
					} else { // Reset bpm
						_bpmValue.setText( "---" );
						_averageDelay=0;
					}
					
					_lastMillis = current;
				}
				
				return true;
			}
		}
	);	
	    
	// Begin loopist button handler
	Button button = (Button) findViewById(R.id.begin_button);
	if( button != null ) {
		button.setOnClickListener( 
			new View.OnClickListener() 
			{ 
				public void onClick(View v) 
				{
					ProgressDialog pd = ProgressDialog.show(_context, "Starting...", "Initializing loopist engine and view.",true);
					if( _loopistEngine!=null && _loopistView!=null ) {
						_loopistView=null; 
						_loopistEngine=null;
					}
					
					// Get the values for bpm,bars and bpb to initialize loopist engine with...
					int bpm=0;
					try {
						bpm = Integer.valueOf(_bpmValue.getText().toString());
					} catch ( java.lang.NumberFormatException e) {
						Toast.makeText(_context, "The BPM values is invalid, please tap BPM button at least 4 times...",Toast.LENGTH_SHORT).show();
						pd.dismiss();
						return;
					}
					int bars=Integer.valueOf((String)_barsSpinner.getSelectedItem());
					int bpb=Integer.valueOf((String)_beatsPerBarSpinner.getSelectedItem());
					
					ByteBuffer pcm=null;
					if( _generateMetronomeTrack.isChecked() ) {
						pcm=ByteBuffer.allocate(40960);
						InputStream is = _context.getResources().openRawResource(R.raw.click_raw);
						pcm.mark();
					
						try {
							int res=0;
							do {
								res=is.read(pcm.array(),res,4096);
								Log.v("Loopist","Read "+res+" bytes from input raw click resource.");
							} while(res>0);
						} catch ( java.io.IOException e) {
						}
					
						pcm.reset();
					}
					_loopistEngine=new LoopistEngine( bpm, bars, bpb, pcm );
					_loopistView=new LoopistView(_loopistEngine,_context);
					_loopistEngine.setListener(_loopistView);
					pd.dismiss();
					setContentView(_loopistView);
				}
			}
		);
		
		
	} else {
		Toast.makeText(this, "Problems with resources...", Toast.LENGTH_SHORT).show();
		Log.v("Loopist","LoopistActivity.onCreate() Resource problem... ");
		finish();
	}
    }
    
    
    @Override
    public void onStart()
    {
	super.onStart();
	
    }
    
    @Override
    public void onResume()
    {
	super.onResume();
	if( _loopistEngine != null ) _loopistEngine.resume();
    }
    
   @Override
    public void onPause()
    {
	super.onPause();
	if( _loopistEngine != null ) _loopistEngine.pause();
    }
}
